' librarian v0.1
'' fbc librarian.bas cmdlineparser.bas

#include "cmdlineparser.bi"

' This program will generate:
' - library.h       - Bank numbers, pointers and lengths arrays.
' - bank?.h         - Data arrays and lengths for each binary, up to 16K in size each

Dim Shared As uByte mainBin (16383)
Dim Shared As Integer binPtr

Sub usage
	Print "usage:"
	Print ""
	Print "librarian.exe in=list.txt library=library.h banks=prefix [firstbank=bankNO] [removebin]"
	Print ""
	Print "* Will add files in list.txt to a resource library"
	Print "* if especified, removebin will trim the _BIN from identifiers."
	Print "* if especified, firstbank indicates the first bank to generate, "
	Print "  first bank will be 0 if not especified."
End Sub

Function MyReplace (Byval subject As String, find As String, replace As String) As String
	Dim As Integer it
	For it = 1 To Len (subject)
		If Mid (subject, it, 1) = find Then Mid (subject, it, 1) = replace
	Next it
	Return subject
End Function

Function procruste (subject As String, n As Integer) As String
	If Len (subject) < n Then
		subject = subject + Space (n - Len (subject))
	End If
	Return subject
End Function

Sub writeBin (b As uByte)
	mainBin (binPtr) = b
	binPtr = binPtr + 1
End Sub

Type BinEntry
	fileName As String
	fileSize As Integer
End Type

Dim As BinEntry binaryList (255)
Dim As Integer fList, fIn, fOut, fL, i, j, k, binaryListIndex
Dim As String linea, ident
Dim As String idents (255)
Dim As Integer identsBanks (255)
Dim As Integer identsIdx
Dim As String mandatory (2) = {"list", "library", "banks"}
Dim As String pathprefix
Dim As Integer removebin
Dim As Integer curBank
Dim As Integer newBank
Dim As Integer byteCount
Dim As uByte d
Dim As Integer bankMaxItems (31)
Dim As Integer bankMaxSize (31)
Dim As Integer bankItems (31, 255)
Dim As Integer maxBanks
Dim As Integer firstBank

Print "librarian v0.1.20180519"

'' Parse the command line

sclpParseAttrs
If Not sclpCheck (mandatory ()) Then usage: End

removebin = (sclpGetValue ("removebin") <> "")

fList = FreeFile
Open sclpGetValue ("list") For Input As #fList

binaryListIndex = 0
While Not Eof (fList)
	Line Input #fList, linea
	linea = Trim (linea, Any Chr (9) & " ")
	binaryList (binaryListIndex).fileName = linea
	fIn = FreeFile
	Open linea For Binary As #fIn
	binaryList (binaryListIndex).fileSize = Lof (fIn)
	Close #fIn
	? binaryList (binaryListIndex).fileName & ": " & binaryList (binaryListIndex).fileSize
	binaryListIndex = binaryListIndex + 1
Wend

' Dummy fill of containers.
' Change for a bin packing algorithm later

''
curBank = -1: byteCount = 16384
For i = 0 To binaryListIndex - 1
	If binaryList (i).fileSize + byteCount > 16384 Then
		curBank = curBank + 1
		bankMaxItems (curBank) = 0
		byteCount = 0
	End If
	bankItems (curBank, bankMaxItems (curBank)) = i
	bankMaxItems (curBank) = bankMaxItems (curBank) + 1
	byteCount = byteCount + binaryList (i).fileSize	
	bankMaxSize (curBank) = byteCount
Next i
''


identsIdx = 0
firstBank = Val (sclpGetValue ("firstbank"))
For i = 0 To curBank
	fOut = FreeFile
	Print "  Opening " & sclpGetValue ("banks") & "_" & Lcase (Hex (i, 2)) & ".h"
	Open sclpGetValue ("banks") & "_" & Lcase (Hex (i, 2)) & ".h" For Output As #fOut
	Print #fOut, "// " & sclpGetValue ("banks") & "_" & Lcase (Hex (i, 2)) & ".h"
	Print #fOut, "// Generated by librarian.exe v0.1 20180519"
	Print #fOut, "// Copyleft 2018 by The Mojon Twins"
	Print #fOut, ""

	byteCount = 0

	For j = 0 To bankMaxItems (i) - 1
		binaryListIndex = bankItems (i, j)
		ident = binaryList (binaryListIndex).fileName

		If removebin Then
			If Len (ident) > 4 Then
				If Right (ident, 4) = ".bin" Then
					ident = Left (ident, Len (ident) - 4)
				End If
			End If
		End If
		ident = MyReplace (MyReplace (ident, "\", "_"), ".", "_")
		idents (identsIdx) = ident

		' Read mainBin
		Print "    Reading " & binaryList (binaryListIndex).fileName;
		fIn = FreeFile
		Open binaryList (binaryListIndex).fileName For Binary As #fIn
		binPtr = 0
		While Not Eof (fIn)
			Get #fIn, , d
			writeBin d
		Wend
		Close #fIn
		Print " - " & binPtr & " bytes read."

		' Write
		Print "    Writing data to bank file." 

		Print #fOut, "#define " & Ucase (ident) & "_BANK " & (i + firstBank)
		Print #fOut, "#define " & Ucase (ident) & "_LEN  " & binPtr
		Print #fOut, "const unsigned char " & ident & " [] = {"
		For k = 0 To binPtr - 1
			If k Mod 16 = 0 Then
				Print #fOut, "	";
			End If
			Print #fOut, "0x" & Lcase (Hex (mainBin (k), 2));
			If k < binPtr - 1 Then 
				Print #fOut, ", ";
				If k Mod 16 = 15 Then Print #fOut, ""
			End If
		Next k

		Print #fOut, ""
		Print #fOut, "};"
		Print #fOut, ""

		byteCount = byteCount + binPtr
		identsBanks (identsIdx) = curBank
		identsIdx = identsIdx + 1
	Next j

	Close fOut
	Print "  Closing " & sclpGetValue ("banks") & "_" & Lcase (Hex (i, 2)) & ".h with " & byteCount & " bytes."
Next i

Print "Generating index"

fL = FreeFile
Open sclpGetValue ("library") For Output As #fL
Print #fL, "// Assets library"
Print #fOut, "// Generated by librarian.exe v0.1 20180519"
Print #fOut, "// Copyleft 2018 by The Mojon Twins"
Print #fOut, ""

Print #fOut, "const unsigned char * const library_items [] = {"
For i = 0 To identsIdx - 1
	Print #fOut, "	";
	Print #fOut, idents (i);
	If i < identsIdx - 1 Then Print #fOut, ", " Else Print #fOut, " "
Next i
Print #fOut, "};"
Print #fOut, ""

Print #fOut, "const unsigned char library_banks [] = {"
For i = 0 To identsIdx - 1
	Print #fOut, "	";
	Print #fOut, Ucase (idents (i)) & "_BANK";
	If i < identsIdx - 1 Then Print #fOut, ", " Else Print #fOut, " "	
Next i
Print #fOut, "};"
Print #fOut, ""

Print #fOut, "const unsigned int library_sizes [] = {"
For i = 0 To identsIdx - 1
	Print #fOut, "	";
	Print #fOut, Ucase (idents (i)) & "_LEN";
	If i < identsIdx - 1 Then Print #fOut, ", " Else Print #fOut, " "
Next i
Print #fOut, "};"
Print #fOut, ""

Print #fOut, "// Constants for asset indexes"
For i = 0 To identsIdx - 1
	Print #fOut, "#define RES_" & Ucase (idents (i)) & " " & i
Next i

Close

Print "DONE! " & identsIdx & " entries."
